package com.anji.hyperneat.onlinereinforcement.trainingbank;

import java.util.LinkedList;


public class TrainingBank {
	private LinkedList<TrainingSequence> list;
	private int numSamples;
	private int sampleCap;
	private float acceptPercent;
	
	public TrainingBank() {
		this(-1, 1);
	}
	
	public TrainingBank(int sampleCap) {
		this(sampleCap, 1);
	}
	
	public TrainingBank(int sampleCap, float acceptPercent) {
		this.list = new LinkedList<TrainingSequence>();
		this.numSamples = 0;
		this.sampleCap = sampleCap;
		this.acceptPercent = acceptPercent;
	}
	
	public boolean addTrainingSequence(TrainingSequence sequence) {
		if (sampleCap > -1 && sequence.getNumSamples() + numSamples > sampleCap) return false;
		double accept = Math.random();
		if (accept > acceptPercent) return false;
		
		list.add(sequence);
		numSamples += sequence.getNumSamples();
		return true;
	}
	
	
	public void train() {
		for (TrainingSequence sequence : list) {
			sequence.apply();
		}
	}
	
	public void train(int epochs) {
		for (int i = 0; i < epochs; i++) {
			for (TrainingSequence sequence : list) {
				sequence.apply();
			}
		}
	}
	
	public boolean trainToMseThreshold(float threshold, int maxEpochs) {
		int count = 0;
		float err = 0;
		float mse = 1;
		
		while (mse > threshold && count < maxEpochs) {
			err = 0;
			for (TrainingSequence sequence : list) {
				err += sequence.applyAndGetSqErr();
			}
			mse = err / numSamples;
			count++;
		}
		
		return count >= maxEpochs;
	}
	
	public void clear() {
		list = new LinkedList<TrainingSequence>();
		numSamples = 0;
	}
	
	public int getNumTrainingSequences() {
		return list.size();
	}
}
